/*
 *  Jiki - a small lightweight wiki engine.
 *
 *  Copyright 2008 Peter Halbmayer <phalbmayer@gmail.com
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

package at.pmsa.jiki.conn;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;

import android.util.Log;
import at.pmsa.jiki.conn.http.HTTPRequest;
import at.pmsa.jiki.conn.http.HTTPResponse;
import at.pmsa.jiki.core.JikiGenerator;
import at.pmsa.jiki.util.DBMan;
import at.pmsa.jiki.util.IJConstants;

public class Connection implements Runnable, IJConstants{
	private Socket socket;
	DBMan dbMan;

	public Connection(Socket socket, DBMan m){
		this.socket = socket;
		this.dbMan = m;
	}

	public void run(){
		
		boolean alive = true;
		BufferedReader in = null;
		PrintWriter out = null;
		
		Log.v("Connection", "\nStarting new connection");
		
		try{
			in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
			out = new PrintWriter(socket.getOutputStream());
		}
		catch(IOException ioe){
			Log.e("Connection", "Error opening connection: " + ioe.toString());
			ioe.printStackTrace();
			alive = false;
		}

		if(in != null && out != null){
			ArrayList<String> request = new ArrayList<String>();
			int emptycounter = 0;
			
			while(alive){
				try{
					String line = in.readLine();
//					System.out.println("line: " + line);
					if(line == null){
						alive = false;
						continue;
					}
					if(line.trim().length() == 0){
						emptycounter++;
					}
					
//					if(line.trim().startsWith("GET") || emptycounter >= 1){
					//triggers after header is read
					if(emptycounter >= 1){
						
						if(request.size() > 0){
							
							HTTPRequest req = new HTTPRequest(request.toArray());
							
							if(req.getCommand().equals("POST")){
								
								char contArr[] = new char[req.getContentLength()];
								in.read(contArr, 0, req.getContentLength());
								
								String requestBody = new String(contArr);
								//has to be self defined for J2ME as java.net package
								//not existing in midlet API
							    requestBody = URLDecoder.decode(requestBody, "UTF-8");
							    
								Log.v("", "requestBody " + requestBody);
								req.setContent(requestBody);
							}

							Log.v("Connection", "\nREQUEST:");
							Log.v("Connection", req.printReq());
							
							JikiGenerator gen = new JikiGenerator(req, dbMan);
							HTTPResponse res = gen.handleRequest();
							
							Log.v("Connection", "RESPONSE:");
							Log.v("Connection", res.printRes());
							
							out.print( (res == null) ? "" : res.toString() );
							out.flush();
							out.close();
						}
						request.clear();
						emptycounter = 0;
					}
					
					request.add(line + "\n");
				}
				//the following exception is forced as above logic always reads beyond
				//the end of line does not mean any error
				catch(IOException e){
//					Log.e("Connection", "Error while reading line. Closing connection...");
					alive = false;
				}
				catch(ClassCastException e){
//					Log.e("Connection", "Error while reading line. Closing connection...");
					alive = false;
				}
			}
		}
		Log.v("Connection", "Closing connection gracefully...");
		try{
			socket.close();
		}
		catch(IOException e){
			e.printStackTrace();
			// ignore - we are closing anyways.
		}
	}
	
	void convertArray(char[] contArr){
	   int b1;
	   int b2;
	   int j = 0;
	   for (int i = 0; i < contArr.length; i++) { 
		   if(contArr[i] == '%') { 
			   b1 = Character.digit((char) contArr[++i], 16); 
			   b2 = Character.digit((char) contArr[++i], 16); 

			   contArr[j++] = (char) (((b1 & 0xf) << 4) + (b2 & 0xf)); 
		   }
		   else if(contArr[i] == '+'){
			   contArr[j++] = ' ';
		   }
		   else{
			   contArr[j++] = contArr[i]; 
		   } 
	   } 
	}
}
